package com.note.app.service.impl;

import com.note.app.document.NoteContent;
import com.note.app.dto.SearchRequestDTO;
import com.note.app.dto.SearchResultDTO;
import com.note.app.mapper.NoteMapper;
import com.note.app.mapper.TagMapper;
import com.note.app.repository.NoteContentRepository;
import com.note.app.service.SearchService;
import com.note.common.domain.Note;
import com.note.common.vo.PageResult;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 基于MySQL全文搜索的搜索服务实现
 */
@Slf4j
@Service("mysqlSearchService")
@RequiredArgsConstructor
public class MysqlSearchServiceImpl implements SearchService {

    private final NoteMapper noteMapper;
    private final TagMapper tagMapper;
    private final NoteContentRepository noteContentRepository;

    /**
     * 搜索笔记
     */
    @Override
    public PageResult<SearchResultDTO> searchNotes(Long userId, SearchRequestDTO searchRequest) {
        log.info("MySQL搜索开始 - 用户ID: {}, 搜索请求: {}", userId, searchRequest);
        
        // 获取并解码关键词
        String encodedKeyword = searchRequest.getKeyword();
        String keyword;
        try {
            keyword = new String(Base64.getDecoder().decode(encodedKeyword));
            log.info("关键词解码成功 - 原始编码: {}, 解码后: {}", encodedKeyword, keyword);
            
            // 去除可能包含的引号
            keyword = keyword.replace("\"", "").trim();
            log.info("关键词处理后: {}", keyword);
        } catch (Exception e) {
            log.error("关键词Base64解码失败, 使用原始值", e);
            keyword = encodedKeyword;
        }
        
        if (!StringUtils.hasText(keyword)) {
            // 如果没有关键词，直接返回空结果
            log.warn("搜索关键词为空，返回空结果");
            return PageResult.of(new ArrayList<>(), 0, searchRequest.getPage(), searchRequest.getSize());
        }

        // 获取笔记列表 - 从MySQL中搜索标题匹配的笔记
        // 这里需要在MySQL中对note表添加全文索引: ALTER TABLE note ADD FULLTEXT INDEX idx_title (title)
        List<Note> titleMatchNotes = new ArrayList<>();
        if (searchRequest.getSearchTitle()) {
            log.info("执行标题搜索 - 关键词: {}, 用户ID: {}, 包含公开: {}, 集合ID: {}", 
                     keyword, userId, searchRequest.getIncludePublic(), searchRequest.getCollectionId());
            
            titleMatchNotes = noteMapper.searchNotesByTitle(
                    userId, 
                    searchRequest.getIncludePublic(),
                    searchRequest.getCollectionId(),
                    keyword,
                    searchRequest.getPage() * searchRequest.getSize(),
                    searchRequest.getSize()
            );
            log.info("标题搜索结果数量: {}", titleMatchNotes.size());
        }
        
        // 获取MongoDB中内容匹配的笔记
        List<Note> contentMatchNotes = new ArrayList<>();
        if (searchRequest.getSearchContent()) {
            log.info("执行内容搜索 - 关键词: {}", keyword);
            
            // 在MongoDB中搜索内容
            List<NoteContent> matchContents = noteContentRepository.findByContentContaining(keyword);
            log.info("MongoDB内容匹配结果数量: {}", matchContents.size());
            
            if (!matchContents.isEmpty()) {
                // 获取这些内容对应的笔记IDs
                List<String> contentIds = matchContents.stream()
                        .map(NoteContent::getId)
                        .collect(Collectors.toList());
                log.debug("匹配的内容IDs: {}", contentIds);
                
                // 查询MySQL获取这些内容ID对应的笔记信息
                List<Note> notesFromContent = noteMapper.selectByContentIds(
                        userId, 
                        searchRequest.getIncludePublic(),
                        contentIds
                );
                log.info("根据内容ID查询到的笔记数量: {}", notesFromContent.size());
                
                // 如果有集合ID过滤，再过滤一次
                if (searchRequest.getCollectionId() != null) {
                    notesFromContent = notesFromContent.stream()
                            .filter(note -> searchRequest.getCollectionId().equals(note.getCollectionId()))
                            .collect(Collectors.toList());
                    log.info("集合ID过滤后的笔记数量: {}", notesFromContent.size());
                }
                
                contentMatchNotes.addAll(notesFromContent);
            }
        }
        
        // 合并结果并去重
        Map<Long, Note> mergedNotes = new HashMap<>();
        titleMatchNotes.forEach(note -> mergedNotes.put(note.getId(), note));
        contentMatchNotes.forEach(note -> mergedNotes.put(note.getId(), note));
        log.info("合并后去重的笔记总数: {}", mergedNotes.size());
        
        // 如果需要按标签过滤
        List<Note> finalNotes = new ArrayList<>(mergedNotes.values());
        if (searchRequest.getIncludeTags() != null && !searchRequest.getIncludeTags().isEmpty()) {
            log.info("按标签过滤 - 标签: {}", searchRequest.getIncludeTags());
            
            // 获取标签ID
            List<Long> tagIds = tagMapper.findTagIdsByNames(searchRequest.getIncludeTags());
            log.info("找到的标签IDs: {}", tagIds);
            
            if (!tagIds.isEmpty()) {
                // 获取包含这些标签的笔记IDs
                List<Long> noteIdsWithTags = tagMapper.findNoteIdsByTagIds(tagIds);
                log.info("包含指定标签的笔记IDs: {}", noteIdsWithTags);
                
                // 过滤笔记列表
                finalNotes = finalNotes.stream()
                        .filter(note -> noteIdsWithTags.contains(note.getId()))
                        .collect(Collectors.toList());
                log.info("标签过滤后的笔记数量: {}", finalNotes.size());
            } else {
                // 如果没有匹配的标签，返回空结果
                log.warn("未找到匹配的标签，返回空结果");
                finalNotes = new ArrayList<>();
            }
        }
        
        // 分页处理 - 手动截取当前页的数据
        int total = finalNotes.size();
        int fromIndex = Math.min(searchRequest.getPage() * searchRequest.getSize(), total);
        int toIndex = Math.min(fromIndex + searchRequest.getSize(), total);
        log.info("分页 - 总数: {}, 范围: {}至{}, 页码: {}, 每页大小: {}", 
                 total, fromIndex, toIndex, searchRequest.getPage(), searchRequest.getSize());
        
        List<Note> pagedNotes = fromIndex < toIndex 
            ? finalNotes.subList(fromIndex, toIndex) 
            : new ArrayList<>();
        
        // 转换成DTO
        List<SearchResultDTO> results = new ArrayList<>();
        for (Note note : pagedNotes) {
            SearchResultDTO dto = new SearchResultDTO();
            dto.setNoteId(note.getId());
            dto.setUserId(note.getUserId());
            dto.setCollectionId(note.getCollectionId());
            dto.setTitle(note.getTitle());
            dto.setIsPublic(note.getIsPublic() == 1);
            dto.setCreatedAt(note.getCreatedAt());
            dto.setUpdatedAt(note.getUpdatedAt());
            
            // 获取标签
            List<String> tags = tagMapper.findTagNamesByNoteId(note.getId());
            dto.setTags(tags);
            
            // 获取内容摘要
            if (note.getContentId() != null) {
                Optional<NoteContent> contentOpt = noteContentRepository.findById(note.getContentId());
                if (contentOpt.isPresent()) {
                    String content = contentOpt.get().getContent();
                    
                    // 移除所有HTML标签
                    content = content.replaceAll("<[^>]*>", "");
                    
                    // 创建内容摘要
                    String summary = content.length() > 100 ? content.substring(0, 100) + "..." : content;
                    dto.setContentSummary(summary);
                    
                    // 如果需要，可以在这里实现简单的纯文本摘要
                    if (StringUtils.hasText(keyword) && content.contains(keyword)) {
                        int start = content.indexOf(keyword);
                        int preStart = Math.max(0, start - 20);
                        int postEnd = Math.min(content.length(), start + keyword.length() + 20);
                        String simpleSummary = 
                            (preStart > 0 ? "..." : "") + 
                            content.substring(preStart, postEnd) + 
                            (postEnd < content.length() ? "..." : "");
                        
                        // 保存为纯文本摘要
                        dto.setContentSummary(simpleSummary);
                    }
                }
            }
            
            results.add(dto);
        }
        
        PageResult<SearchResultDTO> pageResult = PageResult.of(results, total, searchRequest.getPage(), searchRequest.getSize());
        log.info("MySQL搜索完成 - 结果数量: {}, 总数: {}", results.size(), total);
        return pageResult;
    }

    @Override
    public boolean indexNote(Note note) {
        return false;
    }

    @Override
    public boolean deleteNoteIndex(Long noteId) {
        return false;
    }
} 